home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / SOCKUSER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-06  |  16.4 KB  |  835 lines

  1. /* Higher level user subroutines built on top of the socket primitives
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  * Mods by PA0GRI
  5.  */
  6. #include "global.h"
  7. #include <stdarg.h>
  8. #include "mbuf.h"
  9. #include "proc.h"
  10. #include "socket.h"
  11. #ifdef    LZW
  12. #include "lzw.h"
  13. #else
  14. #include "usock.h"
  15. #endif
  16. #include "session.h"
  17.  
  18. #if !defined(_lint)
  19. static char rcsid[] OPTIONAL = "$Id: sockuser.c,v 1.33 1997/09/07 00:31:16 root Exp root $";
  20. #endif
  21.  
  22.  
  23. extern void backEmUp (int len);
  24. int sockblock (int s, int value);
  25. extern const char hitEnter[];
  26.  
  27. #ifdef FIFOSERVER
  28. extern int FIFOout;
  29. #endif
  30.  
  31.  
  32. /* Higher-level receive routine, intended for connection-oriented sockets.
  33.  * Can be used with datagram sockets, although the sender id is lost.
  34.  */
  35. int
  36. recv (s, buf, len, flags)
  37. int s;                /* Socket index */
  38. char *buf;            /* User buffer */
  39. int len;            /* Max length to receive */
  40. int flags;            /* Unused; will eventually select oob data, etc */
  41. {
  42. struct mbuf *bp;
  43. int cnt;
  44.  
  45.     if (len == 0)
  46.         return 0;    /* Otherwise would be interp as "all" */
  47.  
  48.     cnt = recv_mbuf (s, &bp, flags, NULLCHAR, (int *) NULL);
  49.     if (cnt > 0) {
  50.         cnt = min (cnt, len);
  51.         (void) pullup (&bp, (unsigned char *) buf, (int16) cnt);
  52.         free_p (bp);
  53.     }
  54.     return cnt;
  55. }
  56.  
  57.  
  58.  
  59. /* Higher level receive routine, intended for datagram sockets. Can also
  60.  * be used for connection-oriented sockets, although from and fromlen are
  61.  * ignored.
  62.  */
  63. int
  64. recvfrom (s, buf, len, flags, from, fromlen)
  65. int s;                /* Socket index */
  66. char *buf;            /* User buffer */
  67. int len;            /* Maximum length */
  68. int flags;            /* Unused; will eventually select oob data, etc */
  69. char *from;            /* Source address, only for datagrams */
  70. int *fromlen;            /* Length of source address */
  71. {
  72. struct mbuf *bp;
  73. register int cnt;
  74.  
  75.     cnt = recv_mbuf (s, &bp, flags, from, fromlen);
  76.     if (cnt > 0) {
  77.         cnt = min (cnt, len);
  78.         (void) pullup (&bp, (unsigned char *) buf, (int16) cnt);
  79.         free_p (bp);
  80.     }
  81.     return cnt;
  82. }
  83.  
  84.  
  85.  
  86. /* High level send routine */
  87. int
  88. send (s, buf, len, flags)
  89. int s;                /* Socket index */
  90. char *buf;            /* User buffer */
  91. int len;            /* Length of buffer */
  92. int flags;            /* Unused; will eventually select oob data, etc */
  93. {
  94. register struct mbuf *bp;
  95. char sock[MAXSOCKSIZE];
  96. int i = MAXSOCKSIZE;
  97.  
  98.     if (getpeername (s, sock, &i) == -1)
  99.         return -1;
  100.     bp = qdata ((unsigned char *) buf, (int16) len);
  101.     return send_mbuf (s, bp, flags, sock, i);
  102. }
  103.  
  104.  
  105.  
  106. /* High level send routine, intended for datagram sockets. Can be used on
  107.  * connection-oriented sockets, but "to" and "tolen" are ignored.
  108.  */
  109. int
  110. sendto (s, buf, len, flags, to, tolen)
  111. int s;                /* Socket index */
  112. char *buf;            /* User buffer */
  113. int len;            /* Length of buffer */
  114. int flags;            /* Unused; will eventually select oob data, etc */
  115. char *to;            /* Destination, only for datagrams */
  116. int tolen;            /* Length of destination */
  117. {
  118. register struct mbuf *bp;
  119.  
  120.     bp = qdata ((unsigned char *) buf, (int16) len);
  121.     return send_mbuf (s, bp, flags, to, tolen);
  122. }
  123.  
  124.  
  125.  
  126. /* Receive a newline-terminated line from a non-blocking input socket,
  127.  * returning # chars read. The end-of-line sequence is recognized and
  128.  * translated into a single '\n'.
  129.  */
  130. int
  131. nb_recvline (s, buf, len)
  132. int s;                /* Socket index */
  133. unsigned char *buf;        /* User buffer */
  134. unsigned len;            /* Length of buffer */
  135. {
  136. int c;
  137. int cnt = 0;
  138.  
  139.     while (len-- > 1) {
  140.         while ((c = recvchar (s)) == EOF) {
  141.             if (errno != EWOULDBLOCK)
  142.                 return -1;
  143.             
  144.             if (kpause (500) == -1)
  145.                 return -1;
  146.         }
  147.         if (buf != (unsigned char *) 0)
  148.             *buf++ = uchar(c);
  149.         cnt++;
  150.         if (uchar (c) == '\n')
  151.             break;
  152.     }
  153.     if (buf != (unsigned char *) 0)
  154.         *buf = '\0';
  155.     return cnt;
  156. }
  157.  
  158.  
  159.  
  160. /* Receive a newline-terminated line from a socket, returning # chars read.
  161.  * The end-of-line sequence is recognized and translated into a single '\n'.
  162.  */
  163. int
  164. recvline (s, buf, len)
  165. int s;                /* Socket index */
  166. unsigned char *buf;        /* User buffer */
  167. unsigned len;            /* Length of buffer */
  168. {
  169. int c;
  170. int cnt = 0;
  171.  
  172.     while (len-- > 1) {
  173.         if ((c = recvchar (s)) == EOF) {
  174.             cnt = -1;
  175.             break;
  176.         }
  177.         if (buf != (unsigned char *) 0)
  178.             *buf++ = uchar(c);
  179.         cnt++;
  180.         if (uchar (c) == '\n')
  181.             break;
  182.     }
  183.     if (buf != (unsigned char *) 0)
  184.         *buf = '\0';
  185.     return cnt;
  186. }
  187.  
  188.  
  189.  
  190. /* Do printf on a user socket */
  191. int
  192. usprintf (int s, const char *fmt,...)
  193. {
  194. va_list args;
  195. int len;
  196.  
  197.     va_start (args, fmt);        /*lint !e718 !e746 */
  198.     len = usvprintf (s, fmt, args);
  199.     va_end (args);
  200.     return len;
  201. }
  202.  
  203.  
  204. /* Printf on standard output socket */
  205. int
  206. tprintf (const char *fmt,...)
  207. {
  208. va_list args;
  209. int len;
  210.  
  211.     va_start (args, fmt);
  212.     len = usvprintf (Curproc->output, fmt, args);
  213.     va_end (args);
  214.     return len;
  215. }
  216.  
  217.  
  218. #if defined(SCREENSAVER) && defined(UNIX)
  219. int16 intrace = 0;
  220. #endif
  221.  
  222. #ifdef TRACE
  223. extern int tracesock;
  224.  
  225.  
  226. /* Print on Tracesession stdout socket */
  227. void
  228. traceprintf (FILE * fp, const char *fmt,...)
  229. {
  230. va_list args;
  231.  
  232. #if defined(SCREENSAVER) && defined(UNIX)
  233.     intrace = 1;
  234. #endif
  235.     va_start (args, fmt);
  236.     if (fp == stdout)    {
  237.         (void) usvprintf (tracesock, fmt, args);
  238.         (void) usflush (tracesock);
  239.     } else
  240.         (void) vfprintf (fp, fmt, args);
  241.     va_end (args);
  242. #if defined(SCREENSAVER) && defined(UNIX)
  243.     intrace = 0;
  244. #endif
  245. }
  246.  
  247. #endif
  248.  
  249.  
  250. #ifdef UNIX
  251. extern void sm_status (int pos, char *str);
  252. #endif
  253.  
  254.  
  255. /* New style - use session manager switch's status entry point */
  256. int
  257. tcmdprintf (const char *fmt,...)
  258. {
  259. va_list args;
  260. char *buf;
  261. int len;
  262.  
  263.     buf = mallocw (SOBUF);
  264.     va_start (args, fmt);
  265.     if ((len = VSPRINTF ((buf, fmt, args))) >= SOBUF) {
  266.         log (-1, "tcmdprintf() buffer overflow");
  267.         where_outta_here (2, "tcmdprintf");
  268.     }
  269.     va_end (args);
  270. #ifdef UNIX
  271.     sm_status (0, buf);
  272. #else
  273.     usputs (Command->proc->output, buf);
  274. #endif
  275.     free (buf);
  276.     return len;
  277. }
  278.  
  279.  
  280.  
  281. #ifdef UNIX
  282. /* Print on Command stdout socket or a file */
  283. int
  284. tfprintf (FILE * fp, const char *fmt,...)
  285. {
  286. va_list args;
  287. int len;
  288.  
  289.     va_start (args, fmt);
  290.     if (fp == stdout)
  291.         len = usvprintf (Command->output, fmt, args);
  292.     else
  293.         len = vfprintf (fp, fmt, args);
  294.     va_end (args);
  295.     return len;
  296. }
  297.  
  298. #endif
  299.  
  300.  
  301.  
  302.  
  303. /* The guts of printf, uses variable arg version of sprintf */
  304. int
  305. usvprintf (int s, const char *fmt, va_list args)
  306. {
  307. int len;
  308. char *buf;
  309.  
  310.     if (strchr (fmt, '%') == NULLCHAR) {
  311.         /* Common case optimization: no args, so we don't
  312.          * need vsprintf()
  313.          */
  314.         buf = strdup (fmt);
  315.         len = (int) strlen (fmt);
  316.     } else {
  317.         /* Use a default value that is hopefully longer than the
  318.          * biggest output string we'll ever print (!)
  319.          */
  320.         buf = mallocw (SOBUF);
  321.         /* Start of mod by N4YYH */
  322.         if ((len = VSPRINTF ((buf, fmt, args))) >= SOBUF) {
  323.             /* It's too late to be sorry. He's dead, Jim. */
  324.             log (s, "usvprintf() has exceeded the size of it's buffer. Restarting NOS.");
  325.             where_outta_here (2, "usvprintf");
  326.         }
  327.         /* End of mod by N4YYH */
  328.     }
  329.     if (usputs (s, buf) == EOF)
  330.         len = -1;
  331.     free (buf);
  332.     return len;
  333. }
  334.  
  335.  
  336. /* Buffered putchar to a socket */
  337. int
  338. usputc (int s, const unsigned char c)
  339. {
  340. struct usock *up;
  341. register struct mbuf *bp;
  342. unsigned char *cp;
  343. /*lint -esym(550,len) */
  344. int newline, len;
  345.  
  346.     if (nullsocket (s)) {
  347.         errno = EBADF;
  348.         return -1;
  349.     }
  350.     up = itop (s);
  351.     if (c == '\n' && (up->flag & SOCK_ASCII)) {
  352.         newline = 1;
  353.         len = (int) strlen (up->eol);
  354.     } else {
  355.         newline = 0;
  356.         len = 1;
  357.     }
  358. #ifndef LZW
  359.     /* Make sure there's room in the current buffer, if any */
  360.     if ((bp = up->obuf) != NULLBUF) {
  361.         if ((bp->cnt >= bp->size - len) && usflush (s) == -1)
  362.             return EOF;
  363.     }
  364. #endif
  365.     if (up->obuf == NULLBUF)     /* Allocate a buffer of appropriate size */
  366.         up->obuf = ambufw (BUFSIZ);
  367.  
  368.     /* Note: the buffer must be larger than the end-of-line sequence! */
  369.     bp = up->obuf;
  370.     cp = &bp->data[bp->cnt];
  371.     if (newline) {
  372.         /* Translate into appropriate end-of-line sequence */
  373. #ifdef    LZW
  374.         for (cp = (unsigned char *) up->eol; *cp != '\0'; cp++)
  375.             if (up->zout == NULLLZW)
  376.                 bp->data[bp->cnt++] = *cp;
  377.             else
  378.                 lzwencode (s, (char) *cp);
  379. #else
  380.         strncpy (cp, up->eol, len);
  381. #endif
  382.     } else {
  383. #ifdef    LZW
  384.         if (up->zout == NULLLZW)
  385.             bp->data[bp->cnt++] = c;
  386.         else
  387.             lzwencode (s, (char) c);
  388.     }
  389. #else
  390.         *cp = c;
  391.     }
  392.     bp->cnt += len;
  393. #endif
  394.     /* Flush if necessary and leave enough room for a coming eol */
  395.     if ((c == up->flush && up->flush != -1) || bp->cnt >= bp->size - 9)
  396.         if (usflush (s) == -1)
  397.             return -1;
  398.  
  399. #ifdef LOOKSESSION
  400.     if (up->look)        /* Some one is looking at us ! */
  401.         usputc (up->look->output, c);
  402. #endif
  403.     return (int) uchar (c);
  404. }
  405. /*lint +esym(550,len) */
  406.  
  407.  
  408.  
  409. /* Put a character to standard output socket */
  410. int
  411. tputc (unsigned char c)
  412. {
  413.     return usputc (Curproc->output, c);
  414. }
  415.  
  416.  
  417.  
  418. #ifndef    oldusputs
  419. /* Buffered puts to a socket */
  420. int
  421. usputs (int s, const char *buf)
  422. {
  423. register struct usock *up;
  424. register struct mbuf *bp;
  425. unsigned char *cp, *wp;
  426. int16 len, clen;
  427. int doflush;
  428. int eol_len = 0;
  429. int16 flushpt;
  430. int ascii;
  431. #ifdef LOOKSESSION
  432. const char *oldbuf;
  433. #endif
  434.  
  435. #ifdef FIFOSERVER
  436.     if (s < SOCKBASE && s == FIFOout)    {
  437.         write (s, buf, strlen (buf));
  438.         return 0;
  439.     }
  440. #endif
  441.     if (nullsocket (s)) {
  442.         errno = EBADF;
  443.         return EOF;
  444.     }
  445.     up = itop (s);
  446. #ifdef LOOKSESSION
  447.     oldbuf = buf;
  448. #endif
  449. #ifdef    LZW
  450.     if (up->zout != NULLLZW) {
  451.         while (*buf != '\0')
  452.             if (usputc (s, uchar(*buf++)) == EOF)
  453.                 return EOF;
  454.         return 0;
  455.     }
  456. #endif
  457.     ascii = up->flag & SOCK_ASCII;
  458.     if (ascii)
  459.         eol_len = (int) strlen (up->eol);
  460.     doflush = (up->flush != -1) && (strchr (buf, up->flush) != NULLCHAR);
  461.     len = (int16) strlen (buf);
  462.  
  463.     while (len != 0) {
  464.         if (up->obuf == NULLBUF) {
  465.             /* Allocate a buffer of appropriate size */
  466.             clen = BUFSIZ;
  467.             up->obuf = ambufw (clen);
  468.         }
  469.         /* Note: the buffer must be larger than the end-of-line sequence! */
  470.         bp = up->obuf;
  471.         wp = &bp->data[bp->cnt];
  472. #ifdef TNOS_68K
  473.         if (ascii && (cp = strchr (buf, '\l')) != (unsigned char *) 0) {
  474. #else
  475.         if (ascii && (cp = (unsigned char *) strpbrk (buf, "\n")) != (unsigned char *) 0) {
  476. #endif
  477.             /* Copy up to, but not including, newline */
  478.             clen = (int16) ((const char *) cp - buf);
  479.         } else     /* Copy whole thing */
  480.             clen = len;
  481.  
  482.         /* ...but no more than the room available */
  483.         clen = min (clen, bp->size - bp->cnt);
  484.         if (clen != 0) {
  485.             memcpy (wp, buf, (size_t) clen);
  486.             wp += clen;
  487.             bp->cnt += clen;
  488.             buf += clen;
  489.             len -= clen;
  490.         }
  491.         /* Set flush threshold to allow for eol, if enabled */
  492.         if (ascii)
  493.             flushpt = (int16) (bp->size - eol_len);
  494.         else
  495.             flushpt = bp->size;
  496.  
  497.         if (ascii && (*buf == '\n') && bp->cnt < flushpt) {
  498.             /* Add appropriate end-of-line sequence */
  499.             strncpy ((char *) wp, up->eol, (size_t) eol_len);
  500.             wp += eol_len;
  501.             bp->cnt += (int16) eol_len;
  502.             buf++;    /* Skip newline in buffer */
  503.             len--;
  504.         }
  505.         if (bp->cnt >= flushpt) {
  506.             /* Buffer full, flush and get another */
  507.             if (usflush (s) == -1)
  508.                 return EOF;
  509.         }
  510.     }
  511.     if (doflush && usflush (s) == -1)
  512.         return EOF;
  513.  
  514. #ifdef LOOKSESSION
  515.     if (up->look)        /* someone is looking at us ! */
  516.         usputs (up->look->output, oldbuf);
  517. #endif
  518.     return 0;
  519. }
  520.  
  521. #else
  522.  
  523.  
  524. int
  525. usputs (int s, register const char *x)
  526. {
  527.     while (*x != '\0')
  528.         if (usputc (s, *x++) == EOF)
  529.             return EOF;
  530.     return 0;
  531. }
  532.  
  533. #endif
  534.  
  535.  
  536.  
  537.  
  538. #ifdef FBBFWD
  539. int 
  540. usputbuf (int s, register const unsigned char *x, int len)
  541. {
  542.     while (--len >= 0)
  543.         if (usputc (s, *x++) == EOF)
  544.             return EOF;
  545.     return 0;
  546. }
  547.  
  548. #endif
  549.  
  550.  
  551.  
  552. /* Put a string to standard output socket */
  553. int
  554. tputs (const char *s)
  555. {
  556.     return usputs (Curproc->output, s);
  557. }
  558.  
  559.  
  560.  
  561. /* Read a raw character from a socket with stream buffering. */
  562. int
  563. rrecvchar (s)
  564. int s;                /* Socket index */
  565. {
  566. register struct usock *up;
  567. register int c;
  568.  
  569.     if (nullsocket (s))
  570.         return EOF;
  571.     up = itop (s);
  572. #ifdef    LZW
  573.     if (up->zin != NULLLZW)
  574.         if ((c = lzwdecode (up)) != -1)
  575.             return c;
  576. #endif
  577. #if 1
  578.     if (up->insertbuf) {
  579.         c = *up->insertptr++;
  580.         if (!*up->insertptr) {
  581.             free (up->insertbuf);
  582.             up->insertbuf = NULLCHAR;
  583.         }
  584.         return c;
  585.     }
  586. #endif
  587.     /* Replenish if necessary */
  588.     if (up->ibuf == NULLBUF && recv_mbuf (s, &up->ibuf, 0, NULLCHAR, 0) <= 0)
  589.         return EOF;
  590.  
  591. #ifdef    LZW
  592.     if (up->zin != NULLLZW)
  593.         if ((c = lzwdecode (up)) != -1)
  594.             return c;
  595.         else
  596.             return rrecvchar (s);    /* needs replenish */
  597. #endif
  598.     c = PULLCHAR (&up->ibuf);    /* returns -1 if eof */
  599.  
  600.     return (c == -1 ? EOF : c);
  601. }
  602.  
  603.  
  604.  
  605. /* This function recognizes the end-of-line sequence for the stream
  606.  * and translates it into a single '\n'.
  607.  */
  608. int
  609. recvchar (s)
  610. int s;                /* Socket index */
  611. {
  612. int c;
  613. register struct usock *up;
  614. int inserted;
  615.  
  616.     if (nullsocket (s))
  617.         return EOF;
  618.  
  619.     up = itop (s);
  620.     inserted = (up->insertbuf) ? 1 : 0;
  621.     c = rrecvchar (s);
  622.  
  623.     if (c != up->eol[0] || !(up->flag & SOCK_ASCII)) {
  624. #ifdef LOOKSESSION
  625.         if (Current != Command && up->look && !inserted && c != EOF)
  626.             usputc (up->look->output, uchar(c));
  627. #endif
  628.         return c;
  629.     }
  630.     /* This is the first char of a eol sequence. If the eol sequence is
  631.      * more than one char long, eat the next character in the input stream.
  632.      */
  633.     if (up->eol[1] != '\0')
  634.         (void) rrecvchar (s);
  635.  
  636. #ifdef LOOKSESSION
  637.     if (up->look && !inserted) {
  638.         usputc (up->look->output, '\n');
  639.         /* In the case 'looking' is done from bbs connection,
  640.          * flush it here... */
  641.         usflush (up->look->output);
  642.     }
  643. #endif
  644.     return '\n';
  645. }
  646.  
  647.  
  648.  
  649. /* Flush output on a socket stream */
  650. int
  651. usflush (int s)
  652. {
  653. register struct usock *up;
  654. struct mbuf *bp;
  655.  
  656.     if (nullsocket (s))
  657.         return -1;
  658.  
  659.     up = itop (s);
  660.     if (up->obuf != NULLBUF) {
  661. #ifdef    LZW
  662.         if (up->zout != NULLLZW)
  663.             lzwflush (up);
  664. #endif
  665.         bp = up->obuf;
  666.         up->obuf = NULLBUF;
  667.         return send_mbuf (s, bp, 0, NULLCHAR, 0);
  668.     }
  669. #ifdef LOOKSESSION
  670.     if (up->look)        /* Some one is looking at us, flush them as well */
  671.         usflush (up->look->output);
  672. #endif
  673.     return 0;
  674. }
  675.  
  676.  
  677.  
  678. /* Flush output socket */
  679. void
  680. tflush ()
  681. {
  682.     usflush (Current->output);
  683. }
  684.  
  685.  
  686.  
  687. /* Print prompt and read one character */
  688. int
  689. keywait (prompt, flush)
  690. const char *prompt;        /* Optional prompt */
  691. int flush;            /* Flush queued input? */
  692. {
  693. int c;
  694. const char *pm;
  695. int block = SOCK_BLOCK;
  696.  
  697.     if (prompt == NULLCHAR)
  698.         block = sockblock (Curproc->input, SOCK_BLOCK);
  699.     if (flush && socklen (Curproc->input, 1) != 0)
  700.         (void) recv_mbuf (Curproc->input, NULLBUFP, 0, NULLCHAR, 0);    /* flush */
  701.     pm = (prompt == NULLCHAR) ? hitEnter : prompt;
  702.     tputs (pm);
  703.     tflush ();
  704.     c = recvchar (Curproc->input);
  705.     backEmUp ((int) strlen (pm));
  706.     if (prompt == NULLCHAR)
  707.         (void) sockblock (Curproc->input, block);
  708.     return (int) c;
  709. }
  710.  
  711.  
  712.  
  713. /* Set the end-of-line sequence on a socket */
  714. int
  715. seteol (int s, const char *seq)
  716. {
  717. register struct usock *up;
  718.  
  719.     /* Do *NOT* use nullsocket() here, since this MAY
  720.        be being called while the socket is being
  721.        constructed, and will BE null at the time. */
  722.     if ((up = itop (s)) == NULLUSOCK)
  723.         return -1;
  724.  
  725.     if (seq != NULLCHAR)
  726.         strncpy (up->eol, seq, sizeof (up->eol));
  727.     else
  728.         *up->eol = '\0';
  729.     return 0;
  730. }
  731.  
  732.  
  733.  
  734. /* Enable/disable eol translation, return previous state */
  735. int
  736. sockmode (int s, int mode)
  737. {
  738. struct usock *up;
  739. int prev;
  740.  
  741.     /* Do *NOT* use nullsocket() here, since this is
  742.        sometimes called while the socket is being
  743.        constructed, and may BE null at the time. */
  744.     if ((up = itop (s)) == NULLUSOCK)
  745.         return -1;
  746.     usflush (s);
  747.     prev = up->flag;
  748.     switch (mode) {
  749.         case SOCK_BINARY:
  750.         case SOCK_ASCII:
  751.             up->flag = mode;
  752.             break;
  753.         default:
  754.             break;
  755.     }
  756.     return prev;
  757. }
  758.  
  759.  
  760.  
  761. /* Specify the character to trigger automatic output buffer
  762.  * flushing, or -1 to disable it. Return the previous setting.
  763.  */
  764. int
  765. setflush (int s, int c)
  766. {
  767. register struct usock *up;
  768. int old;
  769.  
  770.     if (nullsocket (s))
  771.         return -1;
  772.  
  773.     up = itop (s);
  774.     old = up->flush;
  775.     up->flush = c;
  776.     return old;
  777. }
  778.  
  779.  
  780.  
  781. /* Set the block mode on a socket - WG7J.
  782.  * Primarily used on convers.c to prevent backlog of data and
  783.  * usprintf() calls blocking because of it...
  784.  * returns previous mode
  785.  */
  786. int 
  787. sockblock (int s, int value)
  788. {
  789. register struct usock *up;
  790. int oldval;
  791.  
  792.     if (nullsocket (s)) {
  793.         errno = EBADF;
  794.         return -1;
  795.     }
  796.     up = itop (s);
  797.     oldval = up->noblock;
  798.     up->noblock = (char) value;
  799.     return oldval;
  800. }
  801.  
  802.  
  803.  
  804. int 
  805. getblock (int s)
  806. {
  807. register struct usock *up;
  808.  
  809.     if (nullsocket (s)) {
  810.         errno = EBADF;
  811.         return -1;
  812.     }
  813.     up = itop (s);
  814.     return up->noblock;
  815. }
  816.  
  817.  
  818.  
  819. int
  820. nullusock (struct usock *up)
  821. {
  822.     if (up == NULLUSOCK || !up->cb.p) {
  823.         errno = ENOTCONN;
  824.         return 1;
  825.     }
  826.     return 0;
  827. }
  828.  
  829.  
  830. int
  831. nullsocket (int s)
  832. {
  833.     return nullusock (itop (s));
  834. }
  835.